package com.ly.heart.service.king;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.google.gson.Gson;
import com.kingdee.bos.webapi.entity.IdentifyInfo;
import com.kingdee.bos.webapi.entity.RepoRet;
import com.kingdee.bos.webapi.sdk.K3CloudApi;
import com.ly.common.exception.CustomException;
import com.ly.common.utils.DateUtils;
import com.ly.common.utils.SecurityUtils;
import com.ly.common.utils.erp.KingConstUtil;
import com.ly.common.utils.spring.SpringUtils;
import com.ly.heart.domain.*;
import com.ly.heart.domain.king.BaseChildBo;
import com.ly.heart.domain.king.order.*;
import com.ly.heart.domain.king.receiveNotice.*;
import com.ly.heart.domain.request.KingBaseSingleRequest;
import com.ly.heart.domain.response.KingBaseResponse;
import com.ly.heart.domain.response.KingBaseResponseSuccessEntity;
import com.ly.heart.service.IKingOrgService;
import com.ly.heart.service.IKingReceiveNoticeService;
import com.ly.heart.service.IOrderService;
import com.ly.heart.util.CurrentUserUtil;
import com.ly.heart.util.KingCommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;


/**
 * 收料通知单推送Service
 */
@Component
@Slf4j
public class KingReceiveNoticePushService{

    private final SimpleDateFormat dateFormat = new SimpleDateFormat ( "yyyy-MM-dd" );

    @Resource
    private IKingReceiveNoticeService receiveNoticeService;
    @Resource
    private IKingOrgService iKingOrgService;

    /**
     * 公用金蝶推送方法
     * 合并保存，提交，审核三步
     * @param receiveNoticeId
     */
    @Transactional( rollbackFor = Exception.class )
    public void push(String receiveNoticeId){
        KingOrgEntity orgEntity = iKingOrgService.getOne ( new LambdaQueryWrapper<KingOrgEntity>().eq ( KingOrgEntity :: getOrgId, CurrentUserUtil.getCompanyId () ).eq ( KingOrgEntity::getIsDisabled, false ) );
        if ( orgEntity == null ) {
            throw new CustomException ( "请先至系统管理中配置金蝶账套！" );
        }
        IdentifyInfo identifyInfo = KingCommonUtil.getIdentifyInfo ( orgEntity );
        KingReceiveNoticeEntity receiveNotice = receiveNoticeService.selectKingReceiveNoticeEntityById(receiveNoticeId);
        if(Objects.isNull(receiveNotice)){
            throw new CustomException("收料通知单不存在！");
        }
        if(receiveNotice.getIsSend() == KingConstUtil.KING_DATA_IS_SEND_YES){
            throw new CustomException("该单据已推送金蝶,无需重复推送！");
        }
        try {
            K3CloudApi client = new K3CloudApi (identifyInfo);
            save(receiveNotice,client);
            submit(receiveNotice.getDocCode(),client);
            audit(receiveNotice.getDocCode(),client);
            updateSendSuccess(receiveNotice.getId());
        }catch (Exception e){
            e.printStackTrace();
            throw new CustomException("推送收料通知单失败！");
        }

    }

    /**
     * 修改推送状态
     * @param receiveNoticeId
     * @return
     */
    private void updateSendSuccess(String receiveNoticeId){
        KingReceiveNoticeEntity kingReceiveNotice = new KingReceiveNoticeEntity();
        kingReceiveNotice.setId(receiveNoticeId);
        kingReceiveNotice.setIsSend(KingConstUtil.KING_DATA_IS_SEND_YES);
        kingReceiveNotice.setUpdateTime(DateUtils.getNowDate());
        kingReceiveNotice.setUpdateBy(SecurityUtils.getLoginUser().getUser().getUserId());
        boolean flag = receiveNoticeService.updateById(kingReceiveNotice);
        if(!flag){
            throw new CustomException("修改推送状态失败！");
        }
    }


    /**
     * 金蝶-收料通知单保存
     * @param receiveNotice
     * @param client
     */
    public void save(KingReceiveNoticeEntity receiveNotice, K3CloudApi client){
        try{
            String formId = KingConstUtil.PUR_RECEIVEBILL;
            KingBaseSingleRequest singleRequest = new KingBaseSingleRequest ();
            ReceiveNoticeBo receiveNoticeBo = this.assembleKingReceiveNotice(receiveNotice);
            singleRequest.setModel(receiveNoticeBo);
            //调用接口
            String resultJson = client.save(formId, JSONObject.toJSONString(singleRequest));
            //用于记录结果
            Gson gson = new Gson();
            //对返回结果进行解析和校验
            RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class);
            KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
            if (baseResponse.getIsSuccess()) {
                log.info("收料通知单推送成功: {}", gson.toJson(repoRet.getResult()));
                List<KingBaseResponseSuccessEntity> successEntities = baseResponse.getSuccessEntitys ();
                if(!CollectionUtils.isEmpty(successEntities)){
                    String docCode = successEntities.get(0).getNumber();
                    //修改为已推送状态
                    receiveNoticeService.update(new LambdaUpdateWrapper<KingReceiveNoticeEntity>().set(KingReceiveNoticeEntity::getIsSend,KingConstUtil.KING_DATA_IS_SEND_YES).eq(KingReceiveNoticeEntity::getDocCode,docCode));
                }
            } else {
                log.error("收料通知单推送失败: " + gson.toJson(repoRet.getResult().getResponseStatus()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 金蝶-收料通知单提交
     * @param docCode
     * @param client
     */
    public void submit(String docCode, K3CloudApi client){
        try{
            OrderSubmitBo submitBo = new OrderSubmitBo();
            List<String> numbers = new ArrayList<>();
            numbers.add(docCode);
            submitBo.setNumbers(numbers);
            String formId = KingConstUtil.PUR_RECEIVEBILL;
            String resultJson = client.submit(formId, JSON.toJSONString ( submitBo ));
            Gson gson = new Gson();
            RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class);
            KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
            if (baseResponse.getIsSuccess()) {
                log.info("收料通知单提交成功: {}", gson.toJson(repoRet.getResult()));
            } else {
                log.error("收料通知单提交失败: {}",gson.toJson(repoRet.getResult().getResponseStatus()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 金蝶审核方法
     * @param docCode
     * @param client
     */
    public void audit(String docCode,K3CloudApi client){
        try{
            OrderAuditBo auditBo = new OrderAuditBo();
            List<String> numbers = new ArrayList<>();
            numbers.add(docCode);
            auditBo.setNumbers(numbers);
            String formId = KingConstUtil.PUR_RECEIVEBILL;
            String resultJson = client.audit(formId,JSON.toJSONString ( auditBo ));
            Gson gson = new Gson();
            RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class);
            KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
            if (baseResponse.getIsSuccess()) {
                log.info("收料通知单审核成功:{}", gson.toJson(repoRet.getResult()));
            } else {
                log.error("收料通知单审核失败:{}",gson.toJson(repoRet.getResult().getResponseStatus()) );
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }




    private ReceiveNoticeBo assembleKingReceiveNotice(KingReceiveNoticeEntity receiveNotice){
        ReceiveNoticeBo receiveNoticeBo = new ReceiveNoticeBo();
        //单据类型
        FBillTypeIDBo FBillTypeID = new FBillTypeIDBo().setFNUMBER(receiveNotice.getDocType());
        receiveNoticeBo.setFBillTypeID(FBillTypeID);
        //业务类型
        receiveNoticeBo.setFBusinessType(receiveNotice.getDocBusinessType());
        //单据编号
        receiveNoticeBo.setFBillNo(receiveNotice.getDocCode());
        //收料日期
        receiveNoticeBo.setFDate(dateFormat.format(receiveNotice.getReceiveTime()));
        //收料组织 receiveNotice.getReceiveOrgCode()
        BaseChildBo FStockOrgId = new BaseChildBo().setFNumber(KingConstUtil.DEFAULT_ORG);
        receiveNoticeBo.setFStockOrgId(FStockOrgId);
        //收料部门
        BaseChildBo FReceiveDeptId = new BaseChildBo().setFNumber(receiveNotice.getReceiveDeptCode());
        receiveNoticeBo.setFReceiveDeptId(FReceiveDeptId);
        //库存组
        BaseChildBo FStockGroupId = new BaseChildBo().setFNumber(receiveNotice.getInventoryGroup());
        receiveNoticeBo.setFStockGroupId(FStockGroupId);
        //收料员
        BaseChildBo FReceiverId = new BaseChildBo().setFNumber(receiveNotice.getReceiveBy());
        receiveNoticeBo.setFReceiverId(FReceiverId);
        //需求组织 receiveNotice.getRequireDeptCode()
        BaseChildBo FDemandOrgId = new BaseChildBo().setFNumber(KingConstUtil.DEFAULT_ORG);
        receiveNoticeBo.setFDemandOrgId(FDemandOrgId);
        //对应组织
        //采购组织 receiveNotice.getPurchaseOrgCode()
        BaseChildBo FPurOrgId = new BaseChildBo().setFNumber(KingConstUtil.DEFAULT_ORG);
        receiveNoticeBo.setFPurOrgId(FPurOrgId);
        //采购部门
        BaseChildBo FPurDeptId = new BaseChildBo().setFNumber(receiveNotice.getPurchaseDeptCode());
        receiveNoticeBo.setFPurDeptId(FPurDeptId);
        //采购组
        BaseChildBo FPurGroupId = new BaseChildBo().setFNumber(receiveNotice.getPurchaseGroup());
        receiveNoticeBo.setFPurGroupId(FPurGroupId);
        //采购员
        BaseChildBo FPurchaserId = new BaseChildBo().setFNumber(receiveNotice.getPurchaseBy());
        receiveNoticeBo.setFPurchaserId(FPurchaserId);
        //供应商 receiveNotice.getSupplierCode
        BaseChildBo FSupplierId = new BaseChildBo().setFNumber("001");
        receiveNoticeBo.setFSupplierId(FSupplierId);
        //供货方 receiveNotice.getProviderCode()
        BaseChildBo FSupplyId = new BaseChildBo().setFNumber("001");
        receiveNoticeBo.setFSupplyId(FSupplyId);
        //供货方地址 receiveNotice.getProviderAddress()
        receiveNoticeBo.setFSupplyAddress("合肥市蜀山区烈阳");
        //结算方
        BaseChildBo FSettleId = new BaseChildBo().setFNumber(receiveNotice.getBalanceCode());
        receiveNoticeBo.setFSettleId(FSettleId);
        //收款方
        BaseChildBo FChargeId = new BaseChildBo().setFNumber(receiveNotice.getReceiveCode());
        receiveNoticeBo.setFChargeId(FChargeId);
        //货主类型
        receiveNoticeBo.setFOwnerTypeIdHead(receiveNotice.getCargoOwnerType());
        //货主
        BaseChildBo FOwnerIdHead = new BaseChildBo().setFNumber(receiveNotice.getCargoOwner());
        receiveNoticeBo.setFOwnerIdHead(FOwnerIdHead);
        //确认人
        FConfirmerIdBo FConfirmerId = new FConfirmerIdBo().setFUserID(receiveNotice.getConfirmName());
        receiveNoticeBo.setFConfirmerId(FConfirmerId);
        //确认日期
        if(Objects.nonNull(receiveNotice.getConfirmTime())){
            receiveNoticeBo.setFConfirmDate(dateFormat.format(receiveNotice.getConfirmTime()));
        }
        //供货方联系人
        FProviderContactIdBo FProviderContactId = new FProviderContactIdBo().setFCONTACTNUMBER(receiveNotice.getProviderContacts());
        receiveNoticeBo.setFProviderContactId(FProviderContactId);
        //验收方式
        receiveNoticeBo.setFACCTYPE(receiveNotice.getCheckMethod());
        //邮箱
        receiveNoticeBo.setFSupplyEMail(receiveNotice.getEmail());

        /***收料通知单财务信息***/
        FinanceEntityBo FinanceEntity = new FinanceEntityBo();
        //结算组织
        BaseChildBo FSettleOrgId = new BaseChildBo().setFNumber(KingConstUtil.DEFAULT_ORG);
        FinanceEntity.setFSettleOrgId(FSettleOrgId);
        //结算方式
        BaseChildBo FSettleModeId = new BaseChildBo().setFNumber(receiveNotice.getSettlementMethod());
        FinanceEntity.setFSettleModeId(FSettleModeId);
        //结算币别
        BaseChildBo FSettleCurrId = new BaseChildBo().setFNumber(receiveNotice.getSettlementCurrency());
        FinanceEntity.setFSettleCurrId(FSettleCurrId);
        //付款条件
        BaseChildBo FPayConditionId = new BaseChildBo().setFNumber(receiveNotice.getTermOfPayment());
        FinanceEntity.setFPayConditionId(FPayConditionId);

        String orderId = receiveNotice.getMaterialLists().get(0).getRelationId();
        IOrderService orderService = SpringUtils.getBean(IOrderService.class);
        OrderEntity order = orderService.getById(orderId);
        //是否含税
        FinanceEntity.setFIsIncludedTax(order.getIsTax());
        //定价时点
        FinanceEntity.setFPricePoint(order.getPricingTimePoint());
        //价目表
        BaseChildBo FPriceListId = new BaseChildBo().setFNumber(order.getPriceInfoId());
        FinanceEntity.setFPriceListId(FPriceListId);
        //折扣表
        BaseChildBo FDiscountListId = new BaseChildBo().setFNumber(order.getDiscountInfoId());
        FinanceEntity.setFDiscountListId(FDiscountListId);
        //本位币
        BaseChildBo FLocalCurrId = new BaseChildBo().setFNumber(order.getBaseCurrency());
        FinanceEntity.setFLocalCurrId(FLocalCurrId);
        //汇率类型
        BaseChildBo FExchangeTypeId = new BaseChildBo().setFNumber(order.getExchangeRateType());
        FinanceEntity.setFExchangeTypeId(FExchangeTypeId);
        //汇率
        FinanceEntity.setFExchangeRate(order.getExchangeRate());
        //价外税
        FinanceEntity.setFISPRICEEXCLUDETAX(order.getIsExtraPriceTax());
        //整单折扣额
        FinanceEntity.setFAllDisCount(receiveNotice.getWholeDiscountAmount());
        receiveNoticeBo.setFinanceEntity(FinanceEntity);

        /***物料明细信息***/
        List<FDetailEntityBo> FDetailEntity = new ArrayList<>();
        List<KingReceiveNoticeMaterialEntity> materialLists = receiveNotice.getMaterialLists();
        materialLists.stream().filter(Objects::nonNull).forEach(receiveNoticeMaterial ->{
            FDetailEntityBo fDetailEntityBo = new FDetailEntityBo();
            //物料编码
            BaseChildBo FMaterialId = new BaseChildBo().setFNumber(receiveNoticeMaterial.getMaterialCode());
            fDetailEntityBo.setFMaterialId(FMaterialId);
            //收料单位
            BaseChildBo FUnitId = new BaseChildBo().setFNumber(receiveNoticeMaterial.getReceiveUnit());
            fDetailEntityBo.setFUnitId(FUnitId);
            //交货数量
            fDetailEntityBo.setFActReceiveQty(receiveNoticeMaterial.getDeliveryNum());
            //预计到货日期
            fDetailEntityBo.setFPreDeliveryDate(dateFormat.format(receiveNoticeMaterial.getExceptArrivalTime()));
            //供应商交货数量
            fDetailEntityBo.setFSUPDELQTY(receiveNoticeMaterial.getSupplierDeliveryNum());
            //计价单位
            BaseChildBo FPriceUnitId = new BaseChildBo().setFNumber(receiveNoticeMaterial.getPricingUnit());
            fDetailEntityBo.setFPriceUnitId(FPriceUnitId);
            //仓库
            BaseChildBo FStockID = new BaseChildBo().setFNumber(receiveNoticeMaterial.getWarehouseCode());
            fDetailEntityBo.setFStockID(FStockID);
            //库存状态
            BaseChildBo FStockStatusId = new BaseChildBo().setFNumber(receiveNoticeMaterial.getInventoryStatus());
            fDetailEntityBo.setFStockStatusId(FStockStatusId);
            //批号
            BaseChildBo FLot = new BaseChildBo().setFNumber(receiveNoticeMaterial.getBatchNum());
            fDetailEntityBo.setFLot(FLot);
            //拒收原因
            fDetailEntityBo.setFRejectReason(receiveNoticeMaterial.getRejectedReason());
            //是否赠品
            fDetailEntityBo.setFGiveAway(receiveNoticeMaterial.getIsGiveaway());
            //税率
            fDetailEntityBo.setFEntryTaxRate(receiveNoticeMaterial.getTaxRate());
            //单价
            fDetailEntityBo.setFPrice(receiveNoticeMaterial.getPrice());
            //含税单价
            fDetailEntityBo.setFTaxPrice(receiveNoticeMaterial.getContainsTaxPrice());
            //计价基本数量
            fDetailEntityBo.setFPriceBaseQty(receiveNoticeMaterial.getPricingNum());
            //库存单位
            BaseChildBo FStockUnitID = new BaseChildBo().setFNumber(receiveNoticeMaterial.getInventoryUnit());
            fDetailEntityBo.setFStockUnitID(FStockUnitID);
            //库存单位数量
            fDetailEntityBo.setFStockQty(receiveNoticeMaterial.getInventoryUnitNum());
            //验收比例
            fDetailEntityBo.setFACCRATE(receiveNoticeMaterial.getCheckRate());
            //不良品折让金额
            fDetailEntityBo.setFRejectsDiscountAmount(receiveNoticeMaterial.getDefectiveDiscountAmount());
            //入库关联不良品折让金额
            fDetailEntityBo.setFJoinRejectsDiscountAmount(receiveNoticeMaterial.getInventoryDefectiveDiscountAmount());

            KingReceiveNoticeMaterialDetailEntity materialDetail = receiveNoticeMaterial.getMaterialDetail();
            if(Objects.nonNull(materialDetail)){
                //生产日期
                fDetailEntityBo.setFProduceDate(dateFormat.format(materialDetail.getManufactureTime()));
                //需求部门
                BaseChildBo FDemandDeptId = new BaseChildBo().setFNumber(materialDetail.getRequireDept());
                fDetailEntityBo.setFDemandDeptId(FDemandDeptId);
                //需求人
                FDemanderIdBo FDemanderId = new FDemanderIdBo().setFNumber(materialDetail.getRequireBy());
                fDetailEntityBo.setFDemanderId(FDemanderId);
                //计划跟踪号
                fDetailEntityBo.setFMtoNo(materialDetail.getPlanTrackingCode());
                //辅单位
                BaseChildBo FExtAuxUnitId = new BaseChildBo().setFNumber(materialDetail.getAuxiliaryUnit());
                fDetailEntityBo.setFExtAuxUnitId(FExtAuxUnitId);
                //实收数量(辅单位)
                fDetailEntityBo.setFExtAuxUnitQty(materialDetail.getReceivedNumAuxiliaryUnit());
                //检验关联数量
                fDetailEntityBo.setFCheckJoinQty(materialDetail.getCheckRelationNum());
                //合格数量
                fDetailEntityBo.setFReceiveQty(materialDetail.getQualifiedNum());
                //判退数量
                fDetailEntityBo.setFRefuseQty(materialDetail.getRejectNum());
                //样本破坏数量
                fDetailEntityBo.setFSampleDamageQty(materialDetail.getSampleDestructionNum());
                //来料检验
                fDetailEntityBo.setFCheckInComing(materialDetail.getIsIncomingInspection());
                //卡片关联数量
                fDetailEntityBo.setFCardJoinQty(materialDetail.getCardRelationNum());
                //卡片数量
                fDetailEntityBo.setFCardQty(materialDetail.getCardNum());
                //检验数量
                fDetailEntityBo.setFCheckQty(materialDetail.getCheckNum());
                //bom版本
                BaseChildBo FBomId = new BaseChildBo().setFNumber(materialDetail.getBomVer());
                fDetailEntityBo.setFBomId(FBomId);
                //供应商批号
                fDetailEntityBo.setFSupplierLot(materialDetail.getSupplierBatchNum());
                //有效期至
                fDetailEntityBo.setFExpiryDate(dateFormat.format(materialDetail.getValidTo()));
                //备注
                fDetailEntityBo.setFDescription(materialDetail.getRemark());
                //源单类型
                fDetailEntityBo.setFSrcFormId(materialDetail.getSourceDocType());
                //源单单号
                fDetailEntityBo.setFSrcBillNo(materialDetail.getSourceDocType());
                //工废数量
                fDetailEntityBo.setFProcScrapQty(materialDetail.getIndustrialWasteNum());
                //料废数量
                fDetailEntityBo.setFMtrlScrapQty(materialDetail.getMaterialWasteNum());
                //让步接收数量
                fDetailEntityBo.setFCsnReceiveQty(materialDetail.getConcessionAcceptanceNum());
                //不合格关联数量
                fDetailEntityBo.setFRefuseJoinQty(materialDetail.getUnqualifiedRelationNum());
                //让步接收关联数量
                fDetailEntityBo.setFCsnReceiveJoinQty(materialDetail.getConcessionAcceptanceRelationNum());
                //确认交货数量
                fDetailEntityBo.setFConfirmDeliQty(materialDetail.getConfirmDeliveryNum());
                //确认到货日期
                fDetailEntityBo.setFConfirmDeliDate(dateFormat.format(materialDetail.getConfirmArrivalTime()));
                //确认意见
                fDetailEntityBo.setFConfirmInfo(materialDetail.getConfirmAdvice());
            }
            FDetailEntity.add(fDetailEntityBo);
        });
        receiveNoticeBo.setFDetailEntity(FDetailEntity);
        //物流信息
        List<FReceiveTraceBo> FReceiveTrace = new ArrayList<>();
        List<KingReceiveNoticeLogisticsEntity> logisticsList = receiveNotice.getLogisticsList();
        logisticsList.stream().filter(Objects::nonNull).forEach(receiveNoticeLogistics -> {
            FReceiveTraceBo fReceiveTraceBo = new FReceiveTraceBo();
            //物料单号
            fReceiveTraceBo.setFCarryBillNo(receiveNoticeLogistics.getLogisticsNum());
            //寄件人手机号
            fReceiveTraceBo.setFPHONENUMBER(receiveNoticeLogistics.getSenderPhone());
            //起始地点
            fReceiveTraceBo.setFFrom(receiveNoticeLogistics.getStartAddress());
            //终止地点
            fReceiveTraceBo.setFTO(receiveNoticeLogistics.getEndAddress());
            //物料状态
            fReceiveTraceBo.setFState(receiveNoticeLogistics.getLogisticsStatus());
            FReceiveTrace.add(fReceiveTraceBo);
        });
        receiveNoticeBo.setFReceiveTrace(FReceiveTrace);
        return receiveNoticeBo;
    }









}
